package org.zhq.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import org.zhq.pojo.Items;
import org.zhq.service.ItemsEsService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class ItemsEsServiceImpl implements ItemsEsService {
    @Autowired
    private final ElasticsearchTemplate esTemplate;

    public ItemsEsServiceImpl(ElasticsearchTemplate esTemplate) {
        this.esTemplate = esTemplate;
    }

    @Override
    public IPage searchItems(String keywords, String sort, Integer page, Integer pageSize) {
        String fieldName = "itemName";
        String preTags = "<font color='red'>";
        String postTags = "</font>";
        SortBuilder sortBuilder;
        switch (sort) {
            case "c":
                sortBuilder = new FieldSortBuilder("sellCounts").order(SortOrder.DESC);
                break;
            case "p":
                sortBuilder = new FieldSortBuilder("price").order(SortOrder.ASC);
                break;
            default:
                sortBuilder = new FieldSortBuilder("sellCounts").order(SortOrder.DESC);
        }
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery(fieldName, keywords))
                .withHighlightFields(new HighlightBuilder.Field(fieldName)
                        .preTags(preTags)
                        .postTags(postTags))
                .withPageable(PageRequest.of(page, pageSize))
                .withSort(sortBuilder)
                .build();
        SearchResultMapper searchResultMapper = new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                List<Items> itemList = new ArrayList<>();
                SearchHits hits = searchResponse.getHits();
                for (SearchHit hit : hits) {
                    HighlightField hf = hit.getHighlightFields().get(fieldName);
                    String itemNameHf = hf.fragments()[0].toString();
                    Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                    Items items = BeanUtil.mapToBean(sourceAsMap, Items.class, true);
                    items.setItemName(itemNameHf);
                    itemList.add(items);
                }
                if (CollUtil.isNotEmpty(itemList)) {
                    return new AggregatedPageImpl<>((List<T>) itemList, pageable, hits.getTotalHits());
                }
                return new AggregatedPageImpl<>(new ArrayList<>(), pageable, hits.getTotalHits());
            }

            @Override
            public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
                return null;
            }
        };
        AggregatedPage<Items> aggregatedPage = esTemplate.queryForPage(searchQuery, Items.class, searchResultMapper);
        int totalPages = aggregatedPage.getTotalPages();
        int size = aggregatedPage.getSize();
        List<Items> itemsList = aggregatedPage.getContent();
        Page<Items> pageResult = new Page<>();
        pageResult.setRecords(itemsList);
        pageResult.setSize(size);
        pageResult.setTotal(totalPages);
        pageResult.setPages(page + 1);
        return pageResult;
    }
}
